/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2008 INRIA
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
 */
#include "node-info-manager.h"
#include <ostream>
#include <sstream>

NS_LOG_COMPONENT_DEFINE ("NodeInfoManager");

namespace ns3 {
namespace eecityu {

using namespace std;

NodeInfoManager::NodeInfoManager(void)
{
}

NodeInfoManager::NodeInfo::NodeInfo (
  Ptr<Node> n, 
  uint32_t ndId, 
  int32_t ifId, 
  Ipv4Address addr)
{
  // update all the node's information with the arguments supplied
  node = n;
  netDeviceId = ndId;
  interface = ifId;
  address = addr;
}

string 
NodeInfoManager::PrintAllNetDevices (Ptr<Node> n)
{
  NS_LOG_FUNCTION (n);

  // to store the information regarding each interface and
  // net device of the node
  typedef pair<int32_t, Ipv4Address> IfAddrPair_t;
  typedef map<int32_t, Ipv4Address> IfAddrMap_t;
  typedef vector<NodeInfo> NodeInfoVec_t;
  IfAddrMap_t ifAddrMap;
  NodeInfoVec_t nodeInfoVec;
  // obtain the number of net devices installed in the node
  uint32_t nDevs = n->GetNDevices ();
  // walk through all the net deivces on this node and gather
  // the information about the node
  //
  // i is an index for each net device
  for (uint32_t i = 0; i < nDevs; i++) 
  {
    // get each net device
    Ptr<NetDevice> nd = n->GetDevice (i);
    Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
    NS_ASSERT_MSG (ipv4, "Ipv4 protocol object is missing!");
    // get the L3 interface index corresponding to the net device
    int32_t interface = ipv4->GetInterfaceForDevice (nd);
    // get the number of IP addresses associated with the interface i
    uint32_t nAddr = ipv4->GetNAddresses (i);
    for (uint32_t addrIndex = 0; addrIndex < nAddr; addrIndex++)
    {
      // get the IPv4 address corresponding to the net device
      Ipv4Address ipv4Address = ipv4->GetAddress (interface, addrIndex).GetLocal ();
      // update the map storing the interface-to-address mapping
      ifAddrMap.insert (IfAddrPair_t (
        interface, ipv4Address)
        );
      // update the vector storing all information about the node
      nodeInfoVec.push_back (NodeInfo (n, i, interface, ipv4Address));
    }
  }

  // the node's information is gathered. These information is then
  // formatted and printed to a string below
  ostringstream ostr;
  ostr << "Number of net devices = " << nDevs;
  // walk through all the ifAddrMap elements and print
  // them to a string
  for (NodeInfoVec_t::iterator iter = nodeInfoVec.begin ();
    iter != nodeInfoVec.end (); iter ++)
  {
    // retrieve all information about this node
    uint32_t ndId = iter->netDeviceId;
    int32_t interface = iter->interface;
    Ipv4Address address = iter->address;
    // format a string to present the node's information
    ostr << endl
      << "net-device-" << ndId 
      << ":interface-" << interface 
      << " address = " << address;
  }

  return ostr.str ();
}

} // namespace eecityu
} // namespace ns3
